package com.sky.controller.admin;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.builder.ExcelWriterBuilder;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.fill.FillConfig;
import com.sky.constant.MessageConstant;
import com.sky.result.Result;
import com.sky.service.ReportService;
import com.sky.service.WorkspaceService;
import com.sky.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.io.Resources;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;

/**
 * 在线报表控制器
 *
 * @Author Vsunks.v
 * @Date 2023/5/13 9:54
 * @Blog blog.sunxiaowei.net/996.mba
 * @Description: 在线报表控制器
 */
@Slf4j
@RestController
@RequestMapping("/admin/report")
public class ReportController {

    @Autowired
    ReportService reportService;

    @Autowired
    WorkspaceService workspaceService;

    /**
     * 商品销量排行统计在线报表
     *
     * @param begin 报表统计开始时间（以送达时间为准）
     * @param end   报表统计结束时间（以送达时间为准）
     * @return 报表数据
     */
    @GetMapping("/top10")
    public Result<SalesTop10ReportVO> salesTop10(@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate begin,
                                                 @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate end) {
        // 记录日志
        log.info("商品销量排行统计在线报表，报表统计开始时间：{}，报表统计结束时间{}", begin, end);

        // 参数校验

        // 调用service获取返回值，并给出响应
        SalesTop10ReportVO result = reportService.salesTop10(begin, end);
        if (result == null) {
            return Result.error(MessageConstant.REPORT_SALE_TOP10_FAIL);
        }
        return Result.success(result);
    }


    /**
     * 营业额统计在线报表（日销售额）
     *
     * @param begin 报表统计开始时间（以送达时间为准）
     * @param end   报表统计结束时间（以送达时间为准）
     * @return 报表数据
     */
    @GetMapping("/turnoverStatistics")
    public Result<TurnoverReportVO> turnoverStatistics(@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate begin,
                                                       @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate end) {
        // 记录日志
        log.info("营业额统计在线报表（日销售额），报表统计开始时间：{}，报表统计结束时间{}", begin, end);

        // 参数校验

        // 调用service获取返回值，并给出响应
        TurnoverReportVO result = reportService.turnoverStatistics(begin, end);
        return Result.success(result);
    }

    /**
     * 订单量统计在线报表
     * <p>
     * 查询得到：日总订单量、日有效订单量
     * 计算得到：时间段内总订单量、时间段内总有效订单量、时间段内总订单完成率
     *
     * @param begin 报表统计开始时间（以下单时间为准）
     * @param end   报表统计结束时间（以下单时间为准）
     * @return 报表数据
     */
    @GetMapping("/ordersStatistics")
    public Result<OrderReportVO> ordersStatistics(@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate begin,
                                                  @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate end) {
        // 记录日志
        log.info("订单量统计在线报表，报表统计开始时间：{}，报表统计结束时间{}", begin, end);

        // 参数校验

        // 调用service获取返回值，并给出响应
        OrderReportVO result = reportService.ordersStatistics(begin, end);
        return Result.success(result);
    }

    /**
     * 用户量统计在线报表（日总用户量、日新增用户量）
     *
     * @param begin 报表统计开始时间（以注册时间为准）
     * @param end   报表统计结束时间（以注册时间为准）
     * @return 报表数据
     */
    @GetMapping("/userStatistics")
    public Result<UserReportVO> userStatistics(@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate begin,
                                               @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate end) {
        // 记录日志
        log.info("订用户量统计在线报表（日总用户量、日新增用户量），报表统计开始时间：{}，报表统计结束时间{}", begin, end);

        // 参数校验

        // 调用service获取返回值，并给出响应
        UserReportVO result = reportService.userStatistics(begin, end);
        return Result.success(result);
    }

    /**
     * 运营数据报表导出，默认导出30天的数据
     */
    @GetMapping("/export")
    public void export(HttpServletResponse response) throws IOException {
        // 记录日志
        log.info("运营数据报表导出，默认导出30天的数据，当前时间：{}", LocalDateTime.now());

        // 获取要导出的数据
        // 组织一个日期集合
        LocalDate today = LocalDate.now();

        ArrayList<BusinessDataVO> bdVOs = new ArrayList<>();
        BusinessDataVO totalIn30Days = new BusinessDataVO("",0.0,0,0.0,0.0,0);
        for (int i = 1; i <= 30; i++) {
            LocalDate date = today.plusDays(-i);

            BusinessDataVO bdVo = workspaceService.getBusinessData(date);
            bdVo.setDate(date.toString());

            bdVOs.add(bdVo);

            // 汇总入总运营数据对象
            totalIn30Days.setTurnover(bdVo.getTurnover() + totalIn30Days.getTurnover());
            totalIn30Days.setValidOrderCount(bdVo.getValidOrderCount() + totalIn30Days.getValidOrderCount());
            totalIn30Days.setNewUsers(bdVo.getNewUsers() + totalIn30Days.getNewUsers());
        }

        // 计算总的运行数据
        // TODO  计算订单完成率
        // 计算平均客单价
        double avgPrice = BigDecimal.valueOf(totalIn30Days.getTurnover()).
                divide(BigDecimal.valueOf(totalIn30Days.getValidOrderCount()),
                        2,
                        RoundingMode.HALF_UP).doubleValue();
        totalIn30Days.setUnitPrice(avgPrice);

        // 关联模板文件
        InputStream templateIs = Resources.getResourceAsStream("templates/data_template.xlsx");

        // 告诉浏览器响应的内容为xlsx的文件，要在获取输出流之前设置，否则无效
        response.setHeader("Content-Type","application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        // 准备要写的流（和响应相关的输出流）
        ServletOutputStream respOs = response.getOutputStream();


        // 使用EasyExcel导出
        // 创建工作簿对象，并关联模板文件
        ExcelWriter workbook =
                EasyExcel.write(respOs, BusinessDataVO.class).withTemplate(templateIs).build();

        // 创建工作表对象
        WriteSheet workSheet = EasyExcel.writerSheet().build();

        // 准备填充配置文件
        FillConfig fillConfig = FillConfig.builder().forceNewRow(true).build();

        // 填充数据：汇总数据
        workbook.fill(totalIn30Days, fillConfig, workSheet);

        // 填充数据：每天数据
        workbook.fill(bdVOs, workSheet);

        // 关闭流释放资源
        workbook.finish();
        // respOs.close();
        templateIs.close();

    }

}
